package com.learnpilot.datechange.web;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.learnpilot.datechange.datatype.HolidayTypeEnum;
import com.learnpilot.datechange.service.CurrentInternetTime;
import com.learnpilot.datechange.service.DateChanger;
import com.learnpilot.datechange.service.OSServiceController;
import com.learnpilot.datechange.utils.DateChangeConstraint;
import com.learnpilot.datechange.utils.DateUtils;

/**
 * Servlet implementation class DateChangeServlet
 */
@WebServlet(name = "DateChangeServlet", urlPatterns = {"/datechange.do"}, initParams = {@WebInitParam(name="hostFile", value="hosts.properties")})
public class DateChangeServlet extends HttpServlet {
	final static Logger LOG = LoggerFactory.getLogger(DateChangeServlet.class);
	private static final long serialVersionUID = 1L;
	private static final String TIME_SERVICE = "W32Time";
	private DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
	//private Properties knownHost = new Properties();;
	private DateUtils dateUtils = new DateUtils();
	private WebApplicationContext applicationContext;
	private OSServiceController osServiceController;
	private int ANNUAL = 12;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public DateChangeServlet() {
        super();
    }

    @Override
	public void init(ServletConfig config) throws ServletException {
    	//String fileName = config.getInitParameter("hostFile");
    	// We will implement host specific access to the application
        //InputStream input = this.getClass().getClassLoader().getResourceAsStream(fileName);
        //LOG.info("File Name >  "+fileName);
		/*try {
    		knownHost.load(input);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException  e1) {
			e1.printStackTrace();
		}*/
		super.init(config);
	}

    @Override
	public void init() throws ServletException {
    	ServletContext context = getServletContext();
	    applicationContext = WebApplicationContextUtils.getWebApplicationContext(context);
	    osServiceController =  (OSServiceController)applicationContext.getBean("osServiceController");
	    osServiceController.serviceStartUpTypeChange(TIME_SERVICE, DateChangeConstraint.SERVICE_STARTUP_DISABLED);
	    osServiceController.serviceStop(TIME_SERVICE);
    	super.init();
	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	private boolean isLocalRequest(HttpServletRequest request) {
		if("0:0:0:0:0:0:0:1".equals(request.getRemoteHost())){
			return true;
		}
		return false;
	}


	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String systemDate = null;
		if(request.getSession().getAttribute("internet_date") == null){

			CurrentInternetTime currentInternetTime = (CurrentInternetTime) applicationContext.getBean("currentInternetTime");
			request.getSession().setAttribute("internet_date", df.format(currentInternetTime.getCurrentDateFromInternet()));
		}
		String host= isLocalRequest(request) ? "LOCAL" : "REMOTE";
		LOG.info("Host   >   "+host);
		request.getSession().setAttribute("host",host);
		if(request.getParameter("dateChangeBtn") != null && "Change Date".equals(request.getParameter("dateChangeBtn")) ){
			request.setAttribute("inputDate", request.getParameter("date"));
			systemDate = dateChange(request.getParameter("date"));
		}else if(request.getParameter("renewalDateBtn") != null){
			processRenewalDateChange(request, null);
			systemDate = df.format(new Date());
		}else if(request.getParameter("dateChange_R_45_Btn") != null && request.getParameter("r_45_hidden") != null){
				systemDate = processRenewalDateChange(request, "r_45_hidden");
		}else if(request.getParameter("dateChange_R_35_Btn") != null && request.getParameter("r_35_hidden") != null){
				systemDate = processRenewalDateChange(request, "r_35_hidden");
		}else if(request.getParameter("dateChange_R_30_Btn") != null && request.getParameter("r_30_hidden") != null ){
				systemDate = processRenewalDateChange(request, "r_30_hidden");
		}else if(request.getParameter("billingDateBtn") != null){
			processBillingDateChange(request,null);
			systemDate = df.format(new Date());
		}else if(request.getParameter("dateChange_dd1_20_Btn") != null && request.getParameter("dd1_20_hidden") != null){
				systemDate = processBillingDateChange(request,"dd1_20_hidden");
		}else if(request.getParameter("dateChange_dd2_20_Btn") != null && request.getParameter("dd2_20_hidden") != null){
				systemDate = processBillingDateChange(request,"dd2_20_hidden");
		}else if(request.getParameter("dateChange_dd3_20_Btn") != null && request.getParameter("dd3_20_hidden") != null ){
				systemDate = processBillingDateChange(request,"dd3_20_hidden");
		}else if(request.getParameter("dateChange_dd4_20_Btn") != null && request.getParameter("dd4_20_hidden") != null ){
				systemDate = processBillingDateChange(request,"dd4_20_hidden");
		}else if(request.getParameter("dateChange_dd5_20_Btn") != null && request.getParameter("dd5_20_hidden") != null ){
				systemDate = processBillingDateChange(request,"dd5_20_hidden");
		}else if(request.getParameter("dateChange_dd6_20_Btn") != null && request.getParameter("dd6_20_hidden") != null ){
				systemDate = processBillingDateChange(request,"dd6_20_hidden");
		}else if(request.getParameter("dateChange_dd7_20_Btn") != null && request.getParameter("dd7_20_hidden") != null ){
				systemDate = processBillingDateChange(request,"dd7_20_hidden");
		}else if(request.getParameter("dateChange_dd8_20_Btn") != null && request.getParameter("dd8_20_hidden") != null){
				systemDate = processBillingDateChange(request,"dd8_20_hidden");
		}else if(request.getParameter("dateChange_dd9_20_Btn") != null && request.getParameter("dd9_20_hidden") != null){
				systemDate = processBillingDateChange(request,"dd9_20_hidden");
		}else if(request.getParameter("dateChange_dd10_20_Btn") != null && request.getParameter("dd10_20_hidden") != null ){
				systemDate = processBillingDateChange(request,"dd10_20_hidden");
		}
		systemDate = systemDate == null ? df.format(new Date()) : systemDate;
		request.setAttribute("systemDate", systemDate);
		RequestDispatcher rd = request.getRequestDispatcher("/datechange.jsp");
        rd.forward(request, response);

	}

	private String processRenewalDateChange(HttpServletRequest request, String toBeSetDate){
		String renewalDateStr = request.getParameter("renewalDate");
		Date renewalDate = getDateFromString(renewalDateStr);
		request.setAttribute("renewalDateStr", renewalDateStr);
		request.setAttribute("renewal_R_45", df.format(addDate(renewalDate, -45)));
		request.setAttribute("renewal_R_35", df.format(addDate(renewalDate, -35)));
		request.setAttribute("renewal_R_30", df.format(addDate(renewalDate, -30)));
		return toBeSetDate == null ? null : dateChange(request.getParameter(toBeSetDate));
	}
    private String processBillingDateChange(HttpServletRequest request, String toBeSetDate){
		String billingDateStr = request.getParameter("billingDate");
		Date billingDate = getDateFromString(billingDateStr);
		Map<String, String> monthNumberNDateMap = dateUtils.getBillGenerationDate(billingDate, ANNUAL, HolidayTypeEnum.previousday);
		request.setAttribute("billingDateStr", billingDateStr);
		for(int i=1; i<=(ANNUAL-2); i++){
			String filedName = "billing_dd"+i+"_20";
			request.setAttribute(filedName, monthNumberNDateMap.get(String.valueOf(i)));
		}
		return toBeSetDate == null ? null : dateChange(request.getParameter(toBeSetDate));
    }
	@SuppressWarnings("static-access")
	private String dateChange(String inputDateStr){
		DateChanger dateChanger = (DateChanger) applicationContext.getBean("dateChanger");
		dateChanger.changeSystemDate(inputDateStr);
		try {
			 Thread.currentThread().sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return df.format(new Date());

	}
	private Date addDate(Date originalDate, int i) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(originalDate);
		cal.add(Calendar.DAY_OF_MONTH, i);
		return cal.getTime();
	}


	private Date getDateFromString(String renewalDateStr) {
		try {
			return df.parse(renewalDateStr);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings("static-access")
	@Override
	public void destroy() {
    	osServiceController.serviceStartUpTypeChange(TIME_SERVICE, DateChangeConstraint.SERVICE_STARTUP_AUTO);
    	osServiceController.serviceStart(TIME_SERVICE);
		try {
			 Thread.currentThread().sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		super.destroy();
	}

}
